#pragma	once

#include "ZCommon.h"

namespace	Z	{

//------------------------------------------------------------------------------------------------------------------------
inline	int64	readHiResTimerFrequency();
inline	int64	readHiResTimer();

//------------------------------------------------------------------------------------------------------------------------
class	Clock
{
public:
	explicit	Clock(float32 startTimeSeconds = 0.0f)
		:	mTimeCycles(secondsToCycles(startTimeSeconds)),
			mTimeScale(1.0f),
			mPaused(false)	{
	}
	int64	getTimeCycles()	const	{
		return mTimeCycles;
	}
	float32	calcDeltaSeconds(const Clock& other)	{
		int64 dt	= mTimeCycles - other.mTimeCycles;
		return cyclesToSeconds(dt);
	}
	void	update(float32 dtRealSeconds)	{
		if(!mPaused)	{
			int64 dtScaledCycles	= secondsToCycles(dtRealSeconds * mTimeScale);
			mTimeCycles	+= dtScaledCycles;
		}
	}
	void	setPaused(bool paused)	{
		mPaused	= paused;
	}
	bool	isPaused()	const	{
		return mPaused;
	}
	void	setTimeScale(float32 scale)	{
		mTimeScale	= scale;
	}
	float32	getTimeScale()	const	{
		return mTimeScale;
	}
	void	singleStep(float32 frequency)	{
		if(mPaused)	{
			int64 dtScaledCycles	= secondsToCycles(
				(1.0f / frequency) * mTimeScale);
			mTimeCycles	+= dtScaledCycles;
		}
	}
	static	void	initialise()	{
		smCyclesPerSecond	= (float32)readHiResTimerFrequency();
	}
private:
	static	inline	int64	secondsToCycles(float32 timeSeconds)	{
		return (int64)(timeSeconds * smCyclesPerSecond);
	}
	static	inline	float32	cyclesToSeconds(int64 timeCycles)	{
		return (float32)timeCycles / smCyclesPerSecond;
	}

private:
	int64	mTimeCycles;
	float32	mTimeScale;
	bool	mPaused;
	static	float32	smCyclesPerSecond;
};

//------------------------------------------------------------------------------------------------------------------------
inline	int64	readHiResTimerFrequency()
{
	LARGE_INTEGER frequency;
	::QueryPerformanceFrequency(&frequency);
	return frequency.QuadPart;
}

inline	int64	readHiResTimer()
{
	LARGE_INTEGER kPerformanceCount;
	::QueryPerformanceCounter(&kPerformanceCount);
	return kPerformanceCount.QuadPart;
}

}